package com.dake.jdk8.vo;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

/**
 * 泛型 ＜T＞T 与 T 的区别
 * <p>
 * 方法返回前的<T> 是告诉编译器，当前方法的值传入类型可以和类初始化的泛型类型不同，也是就是该方法的泛型类可以自定义，不需要跟类初始化的泛型类相同.
 * </p>
 * 有的方法返回值为 <T> T ，有的方法返回值为 T ,区别在那里 ？
 *
 * @author Administrator
 */
public class Request<E> {

    public static void main(String[] args) {
        List<Integer> numberList = new ArrayList<>();
        numberList.add(1);
        List<String> stringList = new ArrayList<>();
        stringList.add("1");

        Integer listFirst = new Request<String>().getListFirst(numberList);
        // 编译报错，入参由Request<T>的T决定，受Request<T>影响，即左边<>中的String
//        new Request<String>().getListFirst2(numberList);
        // 这样既可
        Integer listFirst3 = new Request<Integer>().getListFirst2(numberList);

        // 无区别
        String listFirst1 = new Request<String>().getListFirst(stringList);
        String listFirst2 = new Request<String>().getListFirst2(stringList);

        System.out.println(listFirst3);
        System.out.println(listFirst1);
        System.out.println(listFirst2);

    }

    /**
     * 方法返回前的 <T> 是告诉编译器，当前方法的值传入类型可以和类初始化的泛型类型不同，也是就是该方法的泛型类可以自定义，不需要跟类初始化的泛型类相同
     * 参数 T
     * 第一个，表示泛型；
     * 第二个，表示返回的是T类型的数据；
     * 第三个，表示限制参数类型为T
     *
     * @param tClass
     * @param <T>
     * @return
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    public <T> T getObject(Class<T> tClass) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException,
            InstantiationException {
        return tClass.getDeclaredConstructor().newInstance();
    }

    private <T> T getListFirst(List<T> data) {
        if (CollectionUtils.isEmpty(data)) {
            return null;
        }
        return data.get(0);
    }

    /**
     * 这个只能传T类型的数据
     *
     * @param data
     * @return
     */
    private E getListFirst2(List<E> data) {
        if (CollectionUtils.isEmpty(data)) {
            return null;
        }
        return data.get(0);
    }
}
